package com.googlecode.gwtbb.server.intermediate;

import com.googlecode.gwtbb.client.shared.entity.Snappable;
import com.googlecode.gwtbb.client.shared.entity.Snapshot;
import com.googlecode.gwtbb.client.shared.entity.properties.GetId;
import com.googlecode.gwtbb.util.ObjectUtils;

import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;

/**
 * When adding a property to a persistent class, the following things need to be kept in sync.
 * - The property in the Base class.
 * - The min/max lengths defined in the Base class.
 * - The property in ClassName.xml. (ensure max lengths)
 * - The property in the ClassNameSnap.xml (ensure max lengths)
 * - Possibly the FormEntry in FormWidget.
 *
 * @author Abraham Grief
 * @version $Id$
 * @since Jun 24, 2008
 */
public class Meta {
	public static <S extends Snapshot> S instantiateSnapshot(Class<S> newInstanceClass, Object src, Collection<String> properties, Long actorId, String process) throws IllegalArgumentException {
		S snap = ObjectUtils.createShallowCopy(newInstanceClass, src, properties);
		snap.setActorId(actorId);
		snap.setProcess(process);
		return snap;
	}

	public static Map<String, Object> instantiateBaseUpdateMap(Snappable oldObj, Date snapDate) {
		return addBaseUpdateProperties(new HashMap<String, Object>(8), oldObj, snapDate);
	}

	public static Map<String, Object> addBaseUpdateProperties(Map<String, Object> updateMap, Snappable oldObj, Date snapDate) {
		updateMap.put(Snappable.SNAP_DATE, snapDate);
		updateMap.put(Snapshot.OLD_SNAP_DATE, oldObj.getSnapDate());
		updateMap.put(GetId.ID, oldObj.getId());
		return updateMap;
	}

	public static Map<String, Object> instantiateUpdateMap(Snappable oldObj, Object newObj, Collection<String> propertiesToUpdate, Date snapDate) {
		Map<String, Object> retVal = ObjectUtils.newPropertyValues(oldObj, newObj, propertiesToUpdate);
		if (!retVal.isEmpty() && !(retVal.size() == 1 && retVal.containsKey(Snappable.SNAP_DATE))) {
			addBaseUpdateProperties(retVal, oldObj, snapDate);
		} else {
			retVal.clear();
		}
		return retVal;
	}
}
